﻿using Common.Msg;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc;
using System.Linq;

namespace CTools.Controllers
{
    [OperaLogger(Order = 99)]
    public class BaseController : Controller
    {
        protected bool isLogger = true;
        protected DoResult<object> doResult = new DoResult<object>();

        public static Dictionary<string, string> dic = new Dictionary<string, string>();
        private static List<string> listActionResult = new List<string>();
        private static object objLock = new object();
        private static bool loadSuccess = false;
        public BaseController()
        {
            if (loadSuccess == false)
            {
                lock (objLock)
                {
                    if (loadSuccess == false)
                    {
                        foreach (var item in GetClasses(""))
                        {
                            foreach (var itemMethod in GetClassMethods(item))
                            {
                                dic.Add(itemMethod.Key, itemMethod.Value);
                            }
                        }
                        loadSuccess = true;
                        listActionResult = dic.Where(s => s.Value == typeof(ActionResult).Name).Select(s => s.Key).ToList();
                    }
                }
            }
        }

        private static List<Type> GetClasses(string nameSpace)
        {
            Assembly asm = Assembly.GetExecutingAssembly();

            List<Type> classlist = new List<Type>();

            foreach (Type type in asm.GetTypes())
            {
                if (type.BaseType.Name.ToLower() != "object" && (string.IsNullOrEmpty(nameSpace) || type.Namespace == nameSpace) && type.Name != "MvcApplication")
                    classlist.Add(type);
            }
            return classlist;
        }
        private static Dictionary<string, string> GetClassMethods(Type classType)
        {
            Dictionary<string, string> methodList = new Dictionary<string, string>();

            foreach (MethodInfo mInfo in classType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly))
            {
                if (mInfo.Name.StartsWith("get_") == false && mInfo.Name.StartsWith("set_") == false && methodList.ContainsKey(classType.FullName + "." + mInfo.Name) == false)
                    methodList.Add(classType.FullName + "." + mInfo.Name, mInfo.ReturnType.Name);
            }

            return methodList;
        }

        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (listActionResult.Count > 0)
            {
                string controllerNamer = filterContext.RouteData.Values["controller"].ToString().ToLower();
                string actionName = filterContext.RouteData.Values["action"].ToString().ToLower();
                string key = listActionResult.Where(s => s.ToLower().EndsWith("." + controllerNamer + "controller." + actionName)).FirstOrDefault();
                if (string.IsNullOrEmpty(key) == false)
                {
                    dic[key] = filterContext.Result.GetType().Name;
                    listActionResult.Remove(key);
                }
            }
            base.OnActionExecuted(filterContext);
        }

        protected override void OnException(ExceptionContext filterContext)
        {
            // 错误日志编写
            string controllerNamer = filterContext.RouteData.Values["controller"].ToString();
            string actionName = filterContext.RouteData.Values["action"].ToString();
            string errMsg = filterContext.Exception.Message;
            if (filterContext.Result is JsonResult jsonData)
            {
                if (jsonData.Data is DoResult<object> doResult)
                {
                    errMsg = doResult.Msg;
                }
            }
            Common.Msg.Log.GetLog.Error(errMsg,
                new { filterContext.Exception.TargetSite.DeclaringType.FullName, controllerNamer, actionName, filterContext.Exception.Source },
                filterContext.Exception);
            // 执行基类中的OnException    
            base.OnException(filterContext);
        }
    }
}